/********************************************************************************************************************************
 * 《C ++ Primer》第五版中文版，读书笔记：按照书中的的示例源码和每一个小章节的课后习题，自己动手写代码实现，作为联系和测试。
 * Date: 2024-03-29 11:57
 * Author: dimon.chen 
 * EMali: 1181302388@qq.com 
 * 
 * 章节: 第三章 字符串，向量和数组
 *       3.2.3 处理string对象中的字符
 * 
 ********************************************************************************************************************************/


///
/// C++11 新标准提供的范围for（range for）语句
///
/// 形式: for(declaration : exprssion)
/// 其中expression不是是一个对象，表示一个序列，declaration 部分定义一个变量，该变量用于访问序列中
/// 的基础元素，每次迭代时
/// declaration部分定义的变量会被初始化为序列中的下一个元素值。
///

#include <iostream>
#include <string>
#include <cctype>             //使用C++标准库定义的C标准库头文件

using std::cin;
using std::cout;
using std::endl;

int main(int argc, char *argv[])
{
    std::string str("some string");

    //范围for（range for）编译序列中每一个基础元素
    //
    for(auto c : str){          //使用auto类型说明符，让编译器根据初始值推断变量的类型，这里变量的
                                //类型是 char c
        c = std::toupper(c);
        cout << c << endl;
    }

    for(char c : str){
        cout << c << endl;
    }


    std::string s("Hello World!!!!");       //直接初始化，s是字符串字面值"Hello World"的副本空白字符除外
    decltype(s.size()) punct_cnt = 0;       //使用关键在 decltype 类型说明符
                                            //让编译器根据表达式的值推断变量的类型

    //s.size()返回值的类型是 string::size_type，这是标准库string类型定义的一种配套类型，体现了标准库
    //与机器无关的特性。
    //实际使用时，使用作用域操作符(::)来表名名字size_type是定义在类string中的。
    //

    for(auto c : s){                        //使用关键字auto类型说明符，让编译器根据变量的初始值推断变量的类型
                                            //使用范围for（range for）来遍历string 对象的每一个字符
        if(ispunct(c))
            ++punct_cnt;
    }
    cout << punct_cnt << " punction characters in " << s << endl;




    std::string s1("Hello World!!!");
    //范围for，使用关键字auto让编译器推断变量c的类型
    //如果要改变string对象中字符的值，需要把循环控制变量定义为引用类型
    for(auto &c : s){
        c = toupper(c);
    }
    cout << s << endl;


    std::string s3("some thing");               //string对象直接初始化，s为字符串字面值的副本，
                                                //空字符除外

    s = s3;                                     //string 对象赋值
    cout << s << endl;

    //下标的类型定义为标注库类型string的配套类型 string::size_type
    //其为 unsigend 无符号类型，保证了不小于0，只要确保下标小于 size() 值
    //
    for(std::string::size_type index = 0;
        index < s.size() && !isspace(s[index]); index++)
                                                //逻辑与运算符，只有运算符左右两侧的运算对象都为真结果为真
                                                //C++语言规定，只有运算符左侧的运算对象为真时,
                                                //才检查运算符右侧的对象
    {
        s[index] = toupper(s[index]);          //使用下标运算符（[ ]）返回string对象指定位置字符的引用
    }
    cout << s << endl;




    const std::string hexdigits = "0123456789ABCDEF";
    cout << "Enter series of numbers between 0 and 15"
         << " separated by space. Hit enter when fininsed:"
         << endl;
    
    std::string result;                     //用于保存16进制字符串
    std::string::size_type n;               //用于保存从输入流总读取的整数

    while(cin >> n){
        cout << "n=" << n << endl;
        if(n < hexdigits.size())
            result += hexdigits[n];
    }

    cout << "you entered: " << result << endl;


    return 0;
}